package edu.fau.scanny.r.stromal.servlet;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;

import edu.fau.scanny.r.RBioconductorUtils;
import edu.fau.scanny.r.RUtils;
import edu.fau.scanny.r.StartRserve;
import edu.fau.scanny.r.stromal.RStromalFactory;
import edu.fau.scanny.r.stromal.model.CelFile;
import edu.fau.scanny.r.stromal.model.IdTable;
import edu.fau.scanny.r.stromal.model.StromalCalculatorModel;
import edu.fau.scanny.r.stromal.model.StromalOutput;
import edu.fau.scanny.stromal.MetaFileUtils;

public class StromalServlet extends HttpServlet {

	private static Map<String, CelFile> chipCelFileMap = null;
	private static String metaFileLocation;
	private static IdTable idTable;

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		System.out.println("result=" + StartRserve.checkLocalRserve());
		metaFileLocation = this.getServletContext().getRealPath(GlobalVariables.META_FILE);

		try {
			chipCelFileMap = MetaFileUtils.chipCelFileMap(metaFileLocation);
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		// mouse gene, entrez id information
		idTable = StromalCalculatorUtils.setUpIdTable(config);
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String servletPath = StringUtils.replace(getServletContext().getRealPath("index.jsp"), "index.jsp", "");

		// parameters from form
		List<String> chips = Arrays.asList(req.getParameterValues("celFiles"));
		String workspaceFile = req.getParameter("workspaceFile");
		String[] wholePartVars = StringUtils.split(req.getParameter("wholePartVar"), ",");

		StromalCalculatorModel model = StromalCalculatorUtils.setUpStromalCalculatorModel(chips, chipCelFileMap, req.getParameter("normalization"),
				Boolean.parseBoolean(req.getParameter("log2")));
		
		
		req.setAttribute("groupMap", model.getGroupFilesMap());

		List<String> allCols = new ArrayList<String>();
		List<String> wholeTissueCols = new ArrayList<String>();
		List<String> lymphocyteCols = new ArrayList<String>();
		List<String> stromalCols = new ArrayList<String>();
		String plymphSt = "";
		Map<String, StromalOutput> stromalOutputs = new LinkedHashMap<String, StromalOutput>();
		RConnection rc = null;
		try {
			rc = new RConnection();
			RUtils.loadWorkSpace(rc, workspaceFile);
			RBioconductorUtils.preprocessCoreLibrary(rc);
			
			String normMethod = req.getParameter("normalization");
			String lymphSpecific = "lymphSpecific";
			StromalCalculatorUtils.asCharacterReadInFile(this, rc, lymphSpecific, "subtract_specific", false, "NULL", true);

			String stromalSpecific = "stromalSpecific";
			StromalCalculatorUtils.asCharacterReadInFile(this, rc, stromalSpecific, "calc_specific", false, "NULL", true);

			String mskList = "MskList";
			StromalCalculatorUtils.asCharacterReadInFile(this, rc, mskList, "mskList", false, "NULL", true);
			
			for (String wholePartVar : wholePartVars) {
				String value = req.getParameter(wholePartVar);
				if ("plymphUser".equals(value))
					value = req.getParameter(wholePartVar + "_plymphoid");
				plymphSt = plymphSt + wholePartVar + ": " + value + "/n";

				String presentCallVar = req.getParameter("PercentPresentWholeTissue." + wholePartVar);
				File boxPlot = File.createTempFile(wholePartVar + "_boxplot_", ".png", new File(servletPath));
				File comparisonPlot = File.createTempFile(wholePartVar + "_comparison_", ".png", new File(servletPath));
				File mskPlotFile = File.createTempFile(wholePartVar + "_msk_", ".png", new File(servletPath));
				

				StromalOutput so = RStromalFactory.getStromalOutputTargetQN(rc, boxPlot, comparisonPlot, presentCallVar, wholePartVar, value, normMethod, model.isLog2(),
							mskPlotFile, mskList, lymphSpecific, stromalSpecific);

				wholeTissueCols.add(so.getWholeTissueS());
				wholeTissueCols.add(so.getPresentCallPercentS());

				lymphocyteCols.add(so.getLymphocyteS());
				lymphocyteCols.add(so.getPresentCallPercentS());

				stromalCols.add(so.getStromalS());
				stromalCols.add(so.getPresentCallPercentS());

				allCols.add(so.getWholeTissueS());
				allCols.add(so.getLymphocyteS());
				allCols.add(so.getStromalS());
				allCols.add(so.getPresentCallPercentS());

				stromalOutputs.put(wholePartVar, so);

			}

			String log2S = WebPageStringUtils.log2S(model.isLog2());
			StromalCalculatorUtils.setFileAttribute(req, rc, wholeTissueCols, "wholeTissue", log2S, idTable,new File(servletPath), stromalOutputs,model.getNormalizationMethod().toString(),log2S);
			StromalCalculatorUtils.setFileAttribute(req, rc, lymphocyteCols, "lymphocyte", log2S, idTable,new File(servletPath),stromalOutputs ,model.getNormalizationMethod().toString(),log2S);
			StromalCalculatorUtils.setFileAttribute(req, rc, stromalCols, "stromal",log2S, idTable,new File(servletPath),stromalOutputs ,model.getNormalizationMethod().toString(),log2S);
			StromalCalculatorUtils.setFileAttribute(req, rc, allCols, "all", log2S, idTable,new File(servletPath),stromalOutputs ,model.getNormalizationMethod().toString(),log2S);

			req.setAttribute("plymphStr", plymphSt);
			req.setAttribute("normalization", model.getNormalizationMethod());
			req.setAttribute("log2", model.isLog2());
			req.setAttribute("stromalOutputs", stromalOutputs);
			rc.close();
			req.getRequestDispatcher("stromal.jsp").forward(req, resp);
		} catch (REngineException ex) {
			rc.close();
			StromalCalculatorUtils.errorHandling(ex, req, resp);
		} catch (REXPMismatchException ex) {
			rc.close();
			StromalCalculatorUtils.errorHandling(ex, req, resp);
		}

	}



	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}

}
